package org.openintents.oiserverdemo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.velocity.app.Velocity;
import org.openintents.webserver.WebServerWrapper;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.AssetManager;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.ToggleButton;

public class OIServerDemoActivity extends Activity {
	private ToggleButton btnStartServer;
	public static Context mContext;
	private TextView txtStatus, txtIPAddress;
	private WebServerWrapper server;
	public static File wwwRoot;
	private HTMLFileGenerator generator;
	public static Cursor notesCursor;
	private boolean started;
	private BroadcastReceiver broadcastReciever;
	private ProgressDialog progressDialog;
	static String TARGET_BASE_PATH;
	
	SharedPreferences preferences;
	
	private boolean enableSSL;
	int port = 8080;
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		mContext = this;
		
		updatePrefs();
		
		btnStartServer = (ToggleButton) findViewById(R.id.btnStartServer);
		txtStatus = (TextView) findViewById(R.id.txtStatus);
		txtIPAddress = (TextView) findViewById(R.id.txtIPAddress);
		btnStartServer.setOnClickListener(btnStartClickListener);
		txtStatus.setText("Status: Server stopped!");
		//txtIPAddress.setText("URL: https://"+getIPAddress()+":"+port);
		updateURL();


		if(!isWifiEnabled()) {
			//showWifiEnableDialog();
			wifiDisabled();
		}
		else {
			wifiEnabled();
		}
		
		Button btnStartWifi = (Button) findViewById(R.id.btnStartWifi);
		
		btnStartWifi.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				Intent wifiIntent = new Intent(
						Settings.ACTION_WIFI_SETTINGS);
				startActivity(wifiIntent);
			}
		});
		
		Button btnSettings = (Button) findViewById(R.id.btnSettings);
		btnSettings.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				startActivity(new Intent(mContext, OIServerPreferenceActivity.class));
			}
		});
		
		broadcastReciever = new BroadcastReceiver() {

			@Override
			public void onReceive(Context context, Intent intent) {
				String action = intent.getAction();
				if(action.equalsIgnoreCase(ConnectivityManager.CONNECTIVITY_ACTION)) {
					updateURL();
				}
				else if(action.equalsIgnoreCase(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
					switch(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, -1)) {
					case WifiManager.WIFI_STATE_DISABLED:
						wifiDisabled();
					break;
					case WifiManager.WIFI_STATE_ENABLED:
						wifiEnabled();
					}
					updateURL();
				}
				else if (action.equalsIgnoreCase(
						OIServerService.STATUS_CHANGED_INTENT)) {
					int status = intent.getIntExtra("status", 0);
					switch (status) {
					case OIServerService.STATUS_STARTED:
						serverStarted();
						break;
					case OIServerService.STATUS_STOPPED:
						serverStopped();
						break;
					case OIServerService.STATUS_ERROR:
						serverStopped();
						showMessage("Error", intent.getStringExtra("msg"));
						break;
					}
				}
			}
		};

		registerBroadcastReciever();
		
		/*
		 * Uri notesURI = Uri.parse("content://org.openintents.notepad/notes");
		 * notesCursor = managedQuery(notesURI, null, null, null, null);
		 */

		try {
			wwwRoot = createDirectory();
		} catch (IOException e) {
			e.printStackTrace();
			showMessage("Error", e.getMessage());
		}

		progressDialog = new ProgressDialog(this);
		progressDialog.setCancelable(false);
		progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
		progressDialog.setMessage("Starting server....");
		progressDialog.setTitle("Please wait....");

		if (OIServerService.isRunning) {
			serverStarted(false);
		}

		/*
		 * File templateDir = new File(wwwRoot.getAbsolutePath()+"/templates");
		 * templateDir.mkdirs();
		 */

		TARGET_BASE_PATH = wwwRoot.getAbsolutePath()+"/";
		
		copyFilesToCache();

		Velocity.setProperty("resource.loader", "file");
		Velocity.setProperty("class.resource.loader.class", 
				"org.apache.velocity.runtime.resource.loader.FileResourceLoader");
		Velocity.setProperty("file.resource.loader.path",
				wwwRoot.getAbsolutePath() + "/templates");
		Velocity.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS,
				"org.openintents.oiserverdemo.VelocityLogger");
		Velocity.init();
	}

	protected void updateURL() {
		String url;
		/*if(enableSSL) {
			url = "URL: \nhttp://"+getIPAddress()+":"+port+"/"+
				  "\nOR\n" +
				  "https://"+getIPAddress()+":"+sslport+"/";
		}
		else
			url = "URL: http://"+getIPAddress()+":"+port+"/";*/
		
		url = "URL: http://"+getIPAddress()+":"+port+"/";
		txtIPAddress.setText(url);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		if (wwwRoot != null)
			wwwRoot.delete();
	}

	public static String getIPAddress() {
		WifiManager wifiManager = (WifiManager) mContext
				.getSystemService(WIFI_SERVICE);
		WifiInfo wifiInfo = wifiManager.getConnectionInfo();
		int ipAddress = wifiInfo.getIpAddress();
		return String.format("%d.%d.%d.%d", (ipAddress & 0xff),
				(ipAddress >> 8 & 0xff), (ipAddress >> 16 & 0xff),
				(ipAddress >> 24 & 0xff));
	}

	public File createDirectory() throws IOException {

		File temp;
		temp = new File(getCacheDir().getAbsolutePath() + "/oiserverdemo");

		if (!temp.exists()) {
			if (!(temp.mkdir())) {

				throw new IOException("Could not create temp directory: "
						+ temp.getAbsolutePath());
			}
		}

		return (temp);
	}

	private OnClickListener btnStartClickListener = new OnClickListener() {

		@Override
		public void onClick(View v) {
			Intent intent = new Intent(mContext, OIServerService.class);

			if (OIServerService.isRunning) {
				// server.stop();
				stopService(intent);
			} else {
				// server = new WebServerWrapper(2222, wwwRoot);
				progressDialog.show();
				
				intent.putExtra("wwwroot", wwwRoot.getAbsolutePath());
				intent.putExtra("port", port);
				intent.putExtra("enableSSL", enableSSL);
				intent.putExtra("host", getIPAddress());
				
				startService(intent);
				// server.serve("Hello World", "GET", new Properties(), new
				// Properties(), new Properties());

				// showMessage("Started",
				// "Server started\nYou can connect to this device using the following address: "+
				// "http://"+getIPAddress()+":2222");
			}
		}
	};
	private int sslport;

	protected void wifiEnabled() {
		txtStatus.setText("Wifi Enabled");
		((Button)findViewById(R.id.btnStartWifi)).setVisibility(View.GONE);
		txtIPAddress.setVisibility(View.VISIBLE);
		//txtIPAddress.setText("URL: https://"+getIPAddress()+":"+port+"/");
		btnStartServer.setVisibility(View.VISIBLE);
		((ImageView)findViewById(R.id.imgWifiIcon)).setImageDrawable(
				getResources().getDrawable(R.drawable.network_wireless));
		updateURL();
	}
	
	protected void wifiDisabled() {
		txtStatus.setText("Wifi Disabled");
		((Button)findViewById(R.id.btnStartWifi)).setVisibility(View.VISIBLE);
		((ImageView)findViewById(R.id.imgWifiIcon)).setImageDrawable(
				getResources().getDrawable(R.drawable.network_wireless_disconnected));
		txtIPAddress.setVisibility(View.GONE);
		btnStartServer.setVisibility(View.GONE);
		Intent intent = new Intent(mContext, OIServerService.class);
		stopService(intent);
	}
	
	protected void serverStarted() {
		serverStarted(true);
	}

	protected void serverStarted(boolean showMessage) {
		started = true;
		txtStatus.setText("Status: Server running!");
		((Button) findViewById(R.id.btnStartServer)).setText("Stop Server");
		if (progressDialog.isShowing()) {
			progressDialog.dismiss();
		}
		btnStartServer.setChecked(true);
		if (showMessage) {
			String msg;
			if(enableSSL)
				msg = "Server started\nYou can connect to this device using the following address: \n"
						+ "http://" + getIPAddress() + ":" + port;
			else
				msg = "Server started\nYou can connect to this device using the following address: \n"
						+ "http://" + getIPAddress() + ":" + port;
			
			showMessage(
					"Started",
					"Server started\nYou can connect to this device using the following address: \n"
							+ "https://" + getIPAddress() + ":" + port);
		}
	}

	protected void serverStopped() {
		progressDialog.dismiss();
		txtStatus.setText("Status: Server stopped!");
		started = false;
		btnStartServer.setChecked(false);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onPause()
	 */
	@Override
	protected void onPause() {
		super.onPause();
		unregisterReceiver(broadcastReciever);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onResume()
	 */
	@Override
	protected void onResume() {
		super.onResume();
		registerBroadcastReciever();
		if(!isWifiEnabled()) {
			wifiDisabled();
		}
		else
			wifiEnabled();
		updatePrefs();
	}

	private void registerBroadcastReciever() {
		IntentFilter filter = new IntentFilter();
		filter.addAction(OIServerService.STATUS_CHANGED_INTENT);
		filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
		filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
		registerReceiver(broadcastReciever, filter);
	}
	
	private boolean isWifiEnabled() {

		ConnectivityManager connManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
		NetworkInfo mWifi = connManager
				.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
		
		return mWifi.isConnected();
	}

	private void showWifiEnableDialog() {
			AlertDialog.Builder ad = new AlertDialog.Builder(this);
			ad.setTitle("Information");
			ad.setMessage("Wifi not enabled. Do you wish to enable it?");
			ad.setPositiveButton("Yes", new DialogInterface.OnClickListener() {

				@Override
				public void onClick(DialogInterface dialog, int which) {
					Intent wifiIntent = new Intent(
							Settings.ACTION_WIFI_SETTINGS);
					startActivity(wifiIntent);
				}
			});
			ad.setNegativeButton("No", new DialogInterface.OnClickListener() {

				@Override
				public void onClick(DialogInterface dialog, int which) {
					dialog.dismiss();
				}
			});
			ad.show();
	}
	
	private void showMessage(String title, String message) {
		AlertDialog.Builder ad = new AlertDialog.Builder(this);
		ad.setTitle(title);
		ad.setMessage(message);
		ad.setPositiveButton("OK", new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int arg1) {
				dialog.dismiss();
			}
		});
		ad.show();
	}
	
	private void updatePrefs() {
		if(preferences == null) {
			preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
			preferences.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener() {
				
				@Override
				public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
						String key) {
					getPrefs(sharedPreferences);
				}
			});
		}
		getPrefs(preferences);
	}
	
	private void getPrefs(SharedPreferences preferences) {
		
		enableSSL = preferences.getBoolean("prefSSLEnable", true);
		port = Integer.parseInt(preferences.getString("prefServerPort", "8080"));
		sslport = Integer.parseInt(preferences.getString("prefSSLServerPort", "8888"));
	}
	
	private void copyFilesToCache() {
		copyFileOrDir(""); // copy all files in assets folder in my project
	}

	private void copyFileOrDir(String path) {
		AssetManager assetManager = this.getAssets();
		String assets[] = null;
		try {
			Log.i("tag", "copyFileOrDir() " + path);
			assets = assetManager.list(path);
			if (assets.length == 0) {
				copyFile(path);
			} else {
				String fullPath = TARGET_BASE_PATH + path;
				Log.i("tag", "path=" + fullPath);
				File dir = new File(fullPath);
				if (!dir.exists() && !path.startsWith("images")
						&& !path.startsWith("sounds")
						&& !path.startsWith("webkit"))
					if (!dir.mkdirs())
						;
				Log.i("tag", "could not create dir " + fullPath);
				for (int i = 0; i < assets.length; ++i) {
					String p;
					if (path.equals(""))
						p = "";
					else
						p = path + "/";

					if (!path.startsWith("images")
							&& !path.startsWith("sounds")
							&& !path.startsWith("webkit"))
						copyFileOrDir(p + assets[i]);
				}
			}
		} catch (IOException ex) {
			Log.e("tag", "I/O Exception", ex);
		}
	}

	private void copyFile(String filename) {
		AssetManager assetManager = this.getAssets();

		InputStream in = null;
		OutputStream out = null;
		String newFileName = null;
		try {
			Log.i("tag", "copyFile() " + filename);
			in = assetManager.open(filename);
			if (filename.endsWith(".jpg")) // extension was added to avoid
											// compression on APK file
				newFileName = TARGET_BASE_PATH
						+ filename.substring(0, filename.length() - 4);
			else
				newFileName = TARGET_BASE_PATH + filename;
			out = new FileOutputStream(newFileName);

			byte[] buffer = new byte[1024];
			int read;
			while ((read = in.read(buffer)) != -1) {
				out.write(buffer, 0, read);
			}
			in.close();
			in = null;
			out.flush();
			out.close();
			out = null;
		} catch (Exception e) {
			Log.e("tag", "Exception in copyFile() of " + newFileName);
			Log.e("tag", "Exception in copyFile() " + e.toString());
		}

	}
}